package com.ciei.dpagm.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ciei.dpagm.common.enums.*;
import com.ciei.dpagm.common.service.BaseService;
import com.ciei.dpagm.entity.ChipParameter;
import com.ciei.dpagm.entity.FormComponent;
import com.ciei.dpagm.entity.FormPropertyDefinition;
import com.ciei.dpagm.entity.FormPropertyOption;
import com.ciei.dpagm.mapper.FormPropertyDefinitionMapper;
import com.ciei.dpagm.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wangyan
 * @date 2021/06/02
 */
@Service
public class FormPropertyDefinitionService extends BaseService<FormPropertyDefinitionMapper, FormPropertyDefinition> {

    @Autowired
    private FormPropertyOptionService formPropertyOptionService;

    @Lazy
    @Autowired
    private FormComponentService formComponentService;

    /**
     * 获取表单属性定义分页列表
     * @return
     */
    public JSONObject getFormPropertyDefinitionPageList(PageParam pageParam){
        JSONObject resultData = new JSONObject();
        Map<String, Object> params=pageParam.getParams();
        int currentPage =pageParam.getCurrentPage();
        int pageSize =pageParam.getPageSize();
        //如果不传或传入空数组，则查询所有
        if (params.get("businessModule") == null || ((List) params.get("businessModule")).isEmpty()){
            params.remove("businessModule");
        }
        JSONObject sortFields = new JSONObject();
        sortFields.put("propertyDefinitionId", APP.DESC);

        IPage<FormPropertyDefinition> page = findPageVue(currentPage, pageSize, params, new String[]{"propertyName"}, null, sortFields,new String[]{"businessModule"});
        List<FormPropertyDefinition> formPropertyDefinitionList= page.getRecords();

        List<FormComponent> componentList = formComponentService.list();
        List<FormPropertyOption> formPropertyOptions = formPropertyOptionService.list();
        JSONArray dataArray = new JSONArray();
        for (FormPropertyDefinition definition : formPropertyDefinitionList){
            JSONObject propertyDefinitionData = new JSONObject();
            propertyDefinitionData.put("propertyDefinitionId",definition.getPropertyDefinitionId());
            propertyDefinitionData.put("propertyKey",definition.getPropertyKey());
            propertyDefinitionData.put("propertyName",definition.getPropertyName());
            propertyDefinitionData.put("componentType",definition.getComponentType());
            propertyDefinitionData.put("valueType",definition.getValueType());
            propertyDefinitionData.put("businessModule",definition.getBusinessModule());
            propertyDefinitionData.put("options", formPropertyOptions.stream().filter(f->definition.getPropertyDefinitionId().equals(f.getPropertyDefinitionId())).collect(Collectors.toList()));
            List<FormComponent> usedList = componentList.stream().filter(c->definition.getPropertyDefinitionId().equals(c.getPropertyDefinitionId())).collect(Collectors.toList());
            propertyDefinitionData.put("isUsed",!usedList.isEmpty());
            dataArray.add(propertyDefinitionData);
        }
        resultData.put(APP.DATA, dataArray);
        resultData.put(APP.TOTAL_COUNT, page.getTotal());
        resultData.put(APP.POS, (currentPage - 1) * pageSize);
        resultData.put(APP.CURRENT_PAGE, page.getCurrent());
        return resultData;
    }

    /**
     * 根据业务模块查询属性定义列表
     * @param businessModule
     * @return
     */
    public JSONObject getFormPropertyDefinitionList(Integer businessModule,Integer componentType){
        if (businessModule == null || componentType == null){
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "请检查参数!");
        }
        List<FormPropertyDefinition> definitionList = findByProperties(new String[]{"businessModule","componentType"},new Integer[]{businessModule,componentType});
        List<FormPropertyOption> formPropertyOptions = formPropertyOptionService.list();
        JSONArray resultArray = new JSONArray();
        for (FormPropertyDefinition definition : definitionList){
            JSONObject definitionData = new JSONObject();
            definitionData.put("propertyDefinitionId",definition.getPropertyDefinitionId());
            definitionData.put("propertyKey",definition.getPropertyKey());
            definitionData.put("propertyName",definition.getPropertyName());
            definitionData.put("valueType",definition.getValueType());
            definitionData.put("options", formPropertyOptions.stream().filter(f->definition.getPropertyDefinitionId().equals(f.getPropertyDefinitionId())).collect(Collectors.toList()));
            resultArray.add(definitionData);
        }
        return JsonUtil.getSuccess("").fluentPut(APP.DATA, resultArray);
    }

    /**
     * 给定业务模块，组件集，添加表单属性定义
     * @param businessModule
     * @param componentArray
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean addFormPropertyDefinition(Integer businessModule,JSONArray componentArray){
        List<FormPropertyDefinition> oldDefinitionList = findByProperties(new String[]{"businessModule"},new Integer[]{businessModule});
        List<String> oldPropertyKeyList = oldDefinitionList.stream().map(FormPropertyDefinition::getPropertyKey).collect(Collectors.toList());
        List<FormPropertyDefinition> newDefinitionList = new ArrayList<>();
        //属性定义是否重复
        Boolean isRepeatOfDefinition = false;
        for (int i = 0; i < componentArray.size(); i++) {
            JSONObject componentData = componentArray.getJSONObject(i);
            String propertyKey = componentData.getString("propertyKey");
            String propertyName = componentData.getString("propertyName");
            //属性定义表，字段不同，但是名称相同
            List<FormPropertyDefinition> repeatedNameList = oldDefinitionList.stream().filter(f->!oldPropertyKeyList.contains(propertyKey)&&f.getPropertyName().equals(propertyName)).collect(Collectors.toList());
            if(!repeatedNameList.isEmpty()){
                isRepeatOfDefinition = true;
                break;
            }
            FormPropertyDefinition repeatedDefinition = oldDefinitionList.stream().filter(f->f.getPropertyKey().equals(propertyKey)).findFirst().orElse(null);
            if (repeatedDefinition != null){
                componentData.put("propertyDefinitionId",repeatedDefinition.getPropertyDefinitionId());
            }else {
               FormPropertyDefinition newDefinition = new FormPropertyDefinition();
               newDefinition.setBusinessModule(businessModule);
               newDefinition.setPropertyKey(propertyKey);
               newDefinition.setPropertyName(propertyName);
               newDefinitionList.add(newDefinition);
               save(newDefinition);

               componentData.put("propertyDefinitionId",newDefinition.getPropertyDefinitionId());
            }
        }
        return isRepeatOfDefinition;
    }

    /**
     * 增加表单字段定义信息
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public JSONObject addFormPropertyDefinition(JSONObject data){
        String propertyKey = data.getString("propertyKey");
        String propertyName = data.getString("propertyName");
        Integer componentType = data.getInteger("componentType");
        Integer valueType = data.getInteger("valueType");
        Integer businessModule = data.getInteger("businessModule");
        JSONArray optionsArray = data.getJSONArray("options");
        if (StringUtil.isNullOrEmpty(propertyKey) || StringUtil.isNullOrEmpty(propertyName) || componentType == null || valueType == null || businessModule == null){
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "请检查参数!");
        }
        List<FormPropertyDefinition> definitionList = findByProperties(new String[]{"businessModule","propertyKey"},new Object[]{businessModule,propertyKey});
        if (!definitionList.isEmpty()){
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "该业务模块下字段key已存在!");
        }
        definitionList = findByProperties(new String[]{"businessModule","propertyName"},new Object[]{businessModule,propertyName});
        if (!definitionList.isEmpty()){
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "该业务模块下字段名称已存在!");
        }
        FormPropertyDefinition newDefinition = new FormPropertyDefinition();
        newDefinition.setPropertyKey(propertyKey);
        newDefinition.setPropertyName(propertyName);
        newDefinition.setComponentType(componentType);
        newDefinition.setValueType(valueType);
        newDefinition.setBusinessModule(businessModule);
        save(newDefinition);
        if (optionsArray != null && !optionsArray.isEmpty()){
            List<FormPropertyOption> insertList = new ArrayList<>();
            for (int i = 0; i < optionsArray.size(); i++) {
                JSONObject option = optionsArray.getJSONObject(i);
                FormPropertyOption newOption = new FormPropertyOption();
                newOption.setPropertyDefinitionId(newDefinition.getPropertyDefinitionId());
                newOption.setLabel(option.getString("label"));
                newOption.setValue(option.getString("value"));
                insertList.add(newOption);
            }
            formPropertyOptionService.saveBatch(insertList);
        }
        return JsonUtil.getSuccess("");
    }

    /**
     * 修改表单字段定义信息
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public JSONObject editFormPropertyDefinition(JSONObject data){
        Integer propertyDefinitionId = data.getInteger("propertyDefinitionId");
        String propertyKey = data.getString("propertyKey");
        String propertyName = data.getString("propertyName");
        Integer componentType = data.getInteger("componentType");
        Integer valueType = data.getInteger("valueType");
        Integer businessModule = data.getInteger("businessModule");
        JSONArray optionsArray = data.getJSONArray("options");
        if (StringUtil.isNullOrEmpty(propertyKey) || StringUtil.isNullOrEmpty(propertyName) || componentType == null || valueType == null || businessModule == null){
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "请检查参数!");
        }
        //查询除自己之外 属性key是否重复
        LambdaQueryWrapper<FormPropertyDefinition> definitionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        definitionLambdaQueryWrapper.eq(FormPropertyDefinition::getPropertyKey,propertyKey);
        definitionLambdaQueryWrapper.eq(FormPropertyDefinition::getBusinessModule,businessModule);
        definitionLambdaQueryWrapper.ne(FormPropertyDefinition::getPropertyDefinitionId,propertyDefinitionId);
        List<FormPropertyDefinition> definitionList = list(definitionLambdaQueryWrapper);
        if (!definitionList.isEmpty()){
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "该业务模块下字段key已存在!");
        }
        //查询除自己之外 属性名称是否重复
        definitionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        definitionLambdaQueryWrapper.eq(FormPropertyDefinition::getPropertyName,propertyName);
        definitionLambdaQueryWrapper.eq(FormPropertyDefinition::getBusinessModule,businessModule);
        definitionLambdaQueryWrapper.ne(FormPropertyDefinition::getPropertyDefinitionId,propertyDefinitionId);
        definitionList = list(definitionLambdaQueryWrapper);
        if (!definitionList.isEmpty()){
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "该业务模块下字段名称已存在!");
        }
        FormPropertyDefinition definition = findById(propertyDefinitionId);
        if (definition == null){
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "无效参数!");
        }
        definition.setPropertyKey(propertyKey);
        definition.setPropertyName(propertyName);
        definition.setComponentType(componentType);
        definition.setValueType(valueType);
        definition.setBusinessModule(businessModule);
        updateById(definition);

        List<FormPropertyOption> oldFormPropertyOptionList = formPropertyOptionService.findByProperties(new String[]{"propertyDefinitionId"},new Integer[]{propertyDefinitionId});
        if (!oldFormPropertyOptionList.isEmpty()){
            formPropertyOptionService.deleteBatchByIds(oldFormPropertyOptionList.stream().map(FormPropertyOption::getOptionId).collect(Collectors.toList()));
        }
        if (optionsArray != null && !optionsArray.isEmpty()){
            List<FormPropertyOption> insertList = new ArrayList<>();
            for (int i = 0; i < optionsArray.size(); i++) {
                JSONObject option = optionsArray.getJSONObject(i);
                FormPropertyOption newOption = new FormPropertyOption();
                newOption.setPropertyDefinitionId(propertyDefinitionId);
                newOption.setLabel(option.getString("label"));
                newOption.setValue(option.getString("value"));
                insertList.add(newOption);
            }
            formPropertyOptionService.saveBatch(insertList);
        }
        return JsonUtil.getSuccess("");
    }

    /**
     * 删除表单定义信息
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public JSONObject deleteFormPropertyDefinition(Integer propertyDefinitionId){
        if (propertyDefinitionId != null) {
            removeById(propertyDefinitionId);
        }
        return JsonUtil.getSuccess("");
    }


    /**
     * 根据被控芯片参数插入表单属性定义字段
     * @param chipParameterList
     */
    public void insertFromChipParameters(List<ChipParameter> chipParameterList){
        List<FormPropertyDefinition> oldPropertyDefinitionList = findByProperty(FormPropertyDefinition::getBusinessModule, FormBusinessModuleEnum.SLAVE_CHIP_PARAMETER.getModuleId());
        List<FormPropertyDefinition> newPropertyDefinitionList = new ArrayList<>();
        for (ChipParameter chipParameter : chipParameterList){
            List<FormPropertyDefinition> propertyDefinitionList = oldPropertyDefinitionList.stream().filter(e ->e.getPropertyKey().equals(chipParameter.getSymbol())).collect(Collectors.toList());
            if (propertyDefinitionList.isEmpty()){
                FormPropertyDefinition newPropertyDefinition = new FormPropertyDefinition();
                newPropertyDefinition.setPropertyKey(chipParameter.getSymbol());
                newPropertyDefinition.setPropertyName(chipParameter.getDescription());
                newPropertyDefinition.setBusinessModule(FormBusinessModuleEnum.SLAVE_CHIP_PARAMETER.getModuleId());
                newPropertyDefinition.setValueType(FormValueTypeEnum.STRING.getTypeId());
                String dataType = chipParameter.getDataType();
                String validValues = chipParameter.getValidValues();
                if (StringUtils.isNotBlank(validValues)){
                    if (validValues.indexOf(",") > -1 || ParameterConfigurationDataTypeEnum.ENUM.getType().equals(dataType)){
                        newPropertyDefinition.setComponentType(FormComponentTypeEnum.SELECT.getTypeId());
                        save(newPropertyDefinition);
                        Integer propertyDefinition = newPropertyDefinition.getPropertyDefinitionId();
                        String displayValues = chipParameter.getDisplayValues();
                        formPropertyOptionService.insertFromValues(propertyDefinition,validValues,displayValues);
                    }
                    if (validValues.indexOf("~") > -1){
                        newPropertyDefinition.setComponentType(FormComponentTypeEnum.INPUT_NUMBER.getTypeId());
                        newPropertyDefinitionList.add(newPropertyDefinition);
                    }
                }else if(StringUtils.isBlank(validValues) && StringUtils.equalsAny(dataType,ParameterConfigurationDataTypeEnum.INTEGER.getType(),ParameterConfigurationDataTypeEnum.FLOAT.getType())) {
                    newPropertyDefinition.setComponentType(FormComponentTypeEnum.INPUT_NUMBER.getTypeId());
                    newPropertyDefinitionList.add(newPropertyDefinition);
                }else if (ParameterConfigurationDataTypeEnum.BOOLEAN.getType().equals(dataType)){
                    newPropertyDefinition.setComponentType(FormComponentTypeEnum.SWITCH.getTypeId());
                    newPropertyDefinitionList.add(newPropertyDefinition);
                }else {
                    newPropertyDefinition.setComponentType(FormComponentTypeEnum.INPUT.getTypeId());
                    newPropertyDefinitionList.add(newPropertyDefinition);
                }
            }
        }
        if (!newPropertyDefinitionList.isEmpty()){
            saveBatch(newPropertyDefinitionList);
        }
    }

}
